package cn.edu.csust.coursecard.utils.storage;

import cn.edu.csust.coursecard.common.CodeEnum;
import cn.edu.csust.coursecard.config.OSSConfig;
import cn.edu.csust.coursecard.exception.BaseException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.AWSSessionCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

@Component
public class DogeCloudUtils implements StorageUtils {
    @Resource
    private OSSConfig config;

    @Resource
    private DogeCloudAPI dogeCloudAPI;

    // 注意：该类内部使用s3Client应使用getS3Client()调用，请勿使用字段本身。
    private AmazonS3 s3Client;

    public AmazonS3 getS3Client() {
        // 未过期则直接返回已存在的实例
        boolean expired = dogeCloudAPI.isKeyExpired();
        if (!expired) {
            return s3Client;
        }
        // 获取key
        AWSSessionCredentials credentials;
        if ("dogecloud".equals(config.getProvider())) {
            credentials = dogeCloudAPI.getServerCredentials();
        } else {
            return null;
        }

        s3Client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSSessionCredentialsProviderImpl(credentials))
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(
                        config.getS3Endpoint(), // 修改为 DogeCloud 控制台存储空间 SDK 参数中的 s3Endpoint
                        "automatic"))
                .build();
        return s3Client;
    }

    @Override
    public void upload(MultipartFile file, String fileName) {
        try {
            byte[] fileBytes = file.getBytes();
            upload(fileBytes, fileName);
        } catch (IOException e) {
            throw new BaseException(CodeEnum.PICTURE_UPLOAD_ERROR.getCode(), "文件上传失败(Internal)");
        }
    }

    @Override
    public void upload(byte[] uploadBytes, String fileName) {
        try {
            InputStream inputStream = new ByteArrayInputStream(uploadBytes);

            this.getS3Client().putObject(config.getS3Bucket(), fileName, inputStream, null);
        } catch (SdkClientException e) {
            throw new BaseException(CodeEnum.PICTURE_UPLOAD_ERROR.getCode(), "文件上传失败");
        }
    }

    @Override
    public void delete(String fileName) {
        this.getS3Client().deleteObject(new DeleteObjectRequest(config.getS3Bucket(), fileName));
    }

    @Override
    public String getUrl() {
        return config.getUrl();
    }
}
